;*********************************************
;       boot.asm
;       copyright (C) BrooksGe
;       2014 - 
;       The boot sector of the disk.
;********************************************* 
        %include "./include/pm.inc"
        extern  _STACK16_END
        global  RMSS
        global  RMSP
        global  CS_Dnor
        global  _enter_rm
        global  PMSP
        global  SS_Dnor
        global  DS_Dnor
        [bits 16]
        [section .text16]
        global  _start
_start: 
        jmp     short _MBR_RUN
        nop
        db      "MSWIN4.1"      ;BS_OEMName
        dw      0200h           ;BPB_BytsPerSec
        db      08h             ;BPB_SecPerClus
        dw      10c0h           ;BPB_RsvdSecCnt
        db      02h             ;BPB_NumFATs
        dw      0000h           ;BPB_RootEntCnt
        dw      0000h           ;BPB_TotSec16
        db      0f8h            ;BPB_Media  
        dw      0000h           ;BPB_FATSz16
        dw      003fh           ;BPB_SecPerTrk
        dw      00ffh           ;BPB_NumHeads
        dd      0000003fh       ;BPB_HiddSec
        dd      001e9fc1h       ;BPB_TotSec32
        dd      000007a0h       ;BPB_FATSz32
        dw      0000h           ;BPB_ExtFlags
        dw      0000h           ;BPB_FSVer
        dd      000002h         ;BPB_RootClus
        dw      0001h           ;BPB_FSInfo
        dw      0006h           ;BPB_BkBootSec
        dd      00000000h  
        dd      00000000h  
        dd      00000000h       ;BPB_Reserved
        db      00h             ;BS_DrvNum
        db      00h             ;BS_Reserved1
        db      29h             ;BS_BootSig
        dd      886e94e6h       ;BS_VolID
        db      "NO NAME    "   ;BS_VolLab
        db      "FAT32   "      ;BS_FilSysType
_MBR_RUN:
        mov     ax, cs
        mov     ds, ax
        mov     ss, ax
        mov     es, ax
        mov     sp, _STACK16_END
        jmp     _enter_pm
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   read one sector, because I do not
;   have many space.
;
;   it use the default dap, and to the default
;   buffer.please note it is not thread-safe.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        global  _read_sector
_read_sector:
	cli
        pusha
        mov     al, [_start + 64]
        cmp     al, 80h
        jnz     .Not_Disk
        push    ds
        mov     ax, 0000h
        mov     ds, ax
        mov     si, _DAP_Pack
        mov     dl, 80h
        mov     ah, 42h
        int     13h
        pop     ds
        jmp     .endread
.Not_Disk:
        push    es
        mov     ax, [_DAP_Pack + 6]
        mov     es, ax
        mov     cx, [_DAP_Pack + 8]
        inc     cx
        mov     dh, 0
        mov     dl, 00h
        mov     bx, [_DAP_Pack + 4]
        mov     al, [_DAP_Pack + 2]
        mov     ah, 02h
        int     13h
        pop     es
.endread:
        popa
        jmp     _from_callback 
               
        [section .data16]

GDTR_Val:
        dw      Desc_len - 1
        dd      Empty_Desc

RMSS:   dw      0
RMSP:   dw      0
PMSP:   dd      200000h
flagfirstin:     db      0
        global  _DAP_Pack
_DAP_Pack:
        db      10h             ;PacketSize
        db      00h             ;Reserved
        dw      01h             ;BlockCount
        dd      00007e00h       ;BufferAddr
        dq      01h             ;BlockNum

        [section .magic_boot]
        db      55h
        db      0aah
        
        
        [section .text16]
        [bits 16]
_enter_pm:
        cli
        mov     ax, ss
        mov     [RMSS], ax
        mov     [RMSP], sp
        in      al, 92h
        or      al, 02h
        out     92h, al
        lgdt    [GDTR_Val]
        mov     eax, cr0
        or      eax, 01h
        mov     cr0, eax
        jmp     dword CS_Desc : _in_pm
_in_rm:       
        mov     ax, 0
        mov     ds, ax 
        mov     ax, [RMSS]
        mov     ss, ax
        mov     sp, [RMSP]
        retf
_from_callback: 
        jmp     near _enter_pm    

        global  _int_call_rm
_int_call_rm:
        mov     ax, 0
        mov     ds, ax 
        mov     ax, [RMSS]
        mov     ss, ax
        mov     sp, [RMSP]
        pop     ebx
        mov     [cs:_intX + 2], bl
        pop     ax
        pop     bx
        pop     cx
        pop     dx
        pop     si
        pop     di
        pop     es
        pop     ds
_intX:
	sti
        int     00h  
        jmp     near _enter_pm 
         
        [section .gdt]
        global  CS_Desc
Empty_Desc:
        dd      0
        dd      0
CS_Desc equ     $ - Empty_Desc
        Descriptor   00000000h, 0fffffh, 9ah
DS_Desc equ     $ - Empty_Desc
        Descriptor   00000000h, 0fffffh, 92h
SS_Desc equ     $ - Empty_Desc
        Descriptor   00000000h, 0fffffh, 92h 
CS_Dnor equ     $ - Empty_Desc
        Descriptor1   00000000h, 00ffffh, 9ah
DS_Dnor equ     $ - Empty_Desc
        Descriptor1   00000000h, 00ffffh, 92h
SS_Dnor equ     $ - Empty_Desc
        Descriptor1   00000000h, 00ffffh, 92h 
Desc_len        equ     $ - Empty_Desc
        
                
        [section .text32]
        [bits 32]
        extern _init
_in_pm:
        mov     ax, DS_Desc
        mov     ds, ax
        mov     es, ax
        mov     ax, SS_Desc
        mov     ss, ax
        mov     esp, [PMSP]
        mov     al, byte [flagfirstin]
        cmp     al, 0
        jnz     .notfist
        mov     al, 1
        mov     byte [flagfirstin], al
        jmp     _init
.notfist:
        popad
        pop     ebp
        retn
        
        global  _pm_call
;       |       |       <- sp before
;       |       |       
;       
;
;
_pm_call:
        push    ebp
        mov     ebp, esp
        pushad
        mov     ebx, [ebp + 8]
        jmp     word CS_Dnor : _enter_rm
        
        [section .text16]
        [bits 16]
_enter_rm:
        mov     ax, SS_Dnor
        mov     ss, ax
        mov     ax, DS_Dnor
        mov     es, ax
        mov     ds, ax
        mov     [PMSP], esp
        xor     eax, eax
        mov     ax, [RMSS]
        shl     eax, 4
        xor     ecx, ecx
        mov     cx, [RMSP]
        add     eax, ecx
        mov     word [eax - 2], 0
        mov     word [eax - 4], bx
        sub     word [RMSP], 4
        in      al, 92h
        and     al, 0fdh
        out     92h, al
        mov     eax, cr0
        and     eax, 0fffffffeh
        mov     cr0, eax
        jmp     0 : _in_rm
        